package com.dingreading.cloud.admin.service.impl;

import com.dingreading.cloud.admin.dto.GoodsAndTypeDto;
import com.dingreading.cloud.admin.dto.GoodsTypeDto;
import com.dingreading.cloud.admin.dto.GoodsTypeInfoDto;
import com.dingreading.cloud.admin.dto.GoodsTypeNumsDto;
import com.dingreading.cloud.admin.entity.GoodsType;
import com.dingreading.cloud.admin.entity.table.GoodsTypeTableDef;
import com.dingreading.cloud.admin.mapper.GoodsTypeMapper;
import com.dingreading.cloud.admin.service.GoodsTypeService;
import com.dingreading.cloud.common.util.AccountUtil;
import com.dingreading.cloud.common.util.NepUtil;
import com.dingreading.cloud.common.util.PageDto;
import com.dingreading.cloud.common.util.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.*;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.dingreading.cloud.admin.entity.table.GoodsTableDef.goods;
import static com.dingreading.cloud.admin.entity.table.GoodsWetPriceTableDef.goodsWetPrice;

/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class GoodsTypeServiceImpl extends BaseServiceImpl<GoodsTypeMapper, GoodsType, GoodsTypeTableDef> implements GoodsTypeService {

    @Override
    protected GoodsTypeTableDef getTable() {
        return GoodsTypeTableDef.goodsType;
    }

    @Resource
    GoodsTypeMapper goodsTypeMapper;

    @Override
    public Page<GoodsTypeDto> pageList(PageUtil pageUtil, String name, Long categoryId, Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (StringUtils.isNotBlank(name))
            condition.and(table.name.like(name).or(goods.name.like(name)));
        if (enabled != null) {
            condition.and(table.enabled.eq(enabled))
                    .and(goods.enabled.eq(enabled));
        }

        QueryWrapper wrapper = QueryWrapper.create()
                .select(getGoodsTypeDto())
                .from(table)
                .leftJoin(goods)
                .on(table.goodsId.eq(goods.id))
                .leftJoin(goodsWetPrice)
                .on(table.id.eq(goodsWetPrice.goodsTypeId))
                .where(condition)
                .orderBy(table.id.asc());

        return getMapper().paginateAs(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, GoodsTypeDto.class);
    }

    private QueryColumn[] getGoodsTypeDto() {
        return new QueryColumn[]{table.id.as("goodsTypeId"), table.name.as("goodsTypeName"),
                table.enabled, table.price, table.img, table.unit, table.weight, table.warnNum,
                table.operationType, table.cooperationType, table.freeDeliveryStatus, table.subjectType,
                table.stockOutMethod, table.goodsId, table.orderNum,
                goods.name.as("goodsName"), goods.categoryId, goods.realStatus,
                QueryMethods.ifNull(goodsWetPrice.usableNum, QueryMethods.number(0)).as("num")
        };
    }

    @Override
    public int deleteByGoodsIdAndIds(Long goodsId, List<Long> ids) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.goodsId.eq(goodsId));
        if (CollectionUtils.isNotEmpty(ids))
            condition.and(table.id.in(ids));
        return getMapper().deleteByCondition(condition);
    }

    @Override
    public List<GoodsType> getByGoodsId(Long goodsId) {
        return getMapper().selectListByCondition(table.goodsId.eq(goodsId));
    }

    @Override
    public boolean updateEnabled(Long goodsTypeId, Integer enabled, String staffUid, String staffName) {
        return UpdateChain.of(GoodsType.class)
                .set(table.enabled, enabled)
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .where(table.id.eq(goodsTypeId))
                .update();
    }

    @Override
    public boolean getCntByUnit(String name) {
        return exists(table.unit.eq(name));
    }

    @Override
    public Page<GoodsTypeNumsDto> goodsStockPage(PageUtil pageUtil, String keyword, Integer orderByType) {
        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("keyword", keyword);
        otherParams.put("orderByType", orderByType);

        return getMapper().xmlPaginate("goodsStockPage", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);
    }

    @Override
    public long getGoodsWarningNum() {
        return goodsTypeMapper.getGoodsWarningNum();
    }

    @Override
    public PageDto<GoodsAndTypeDto> goodsTypePageList(PageUtil pageUtil, String keyword, Integer comboType, Integer enabled) {
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("keyword", keyword);
        otherParams.put("enabled", enabled);
        otherParams.put("comboType", comboType);

        Page<GoodsAndTypeDto> page = getMapper().xmlPaginate("goodsTypePageList", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long count = page.getTotalRow();
        List<GoodsAndTypeDto> list = page.getRecords();

        PageDto<GoodsAndTypeDto> dto = new PageDto<>();
        dto.setTotal(count);
        dto.setList(list);
        return dto;
    }

    @Override
    public List<GoodsTypeInfoDto> typeInfoListByGoodsIdAndEnabled(Long goodsId) {
        QueryWrapper where = QueryWrapper.create()
                .where(table.goodsId.eq(goodsId))
                .orderBy(table.orderNum.asc());
        return getMapper().selectListByQueryAs(where, GoodsTypeInfoDto.class);
    }

    @Override
    public GoodsType getByGoodsIdAndGoodsTypeId(Long goodsId, Long goodsTypeId) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.goodsId.eq(goodsId))
                .and(table.id.eq(goodsTypeId));

        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public int deleteByGoodsIdAndId(Long goodsId, Long id) {
        return getMapper().deleteByCondition(table.goodsId.eq(goodsId).and(table.id.eq(id)));
    }

    @Override
    public List<GoodsAndTypeDto> goodsTypeList(String keyword, Integer comboType, Integer enabled) {
        return goodsTypeMapper.goodsTypeList(keyword, comboType, enabled);
    }

    @Override
    public Page<GoodsTypeNumsDto> goodsWarnPage(PageUtil pageUtil, String keyword) {
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("keyword", keyword);

        return getMapper().xmlPaginate("goodsWarnPage", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);
    }

    @Override
    public GoodsType getLtOrderNum(Long goodsId, Integer comboType, Integer orderNum) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.goodsId.eq(goodsId))
                .and(table.comboType.eq(comboType))
                .and(table.orderNum.lt(orderNum));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.orderNum.desc());

        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public GoodsType getGtOrderNum(Long goodsId, Integer comboType, Integer orderNum) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.goodsId.eq(goodsId))
                .and(table.comboType.eq(comboType))
                .and(table.orderNum.gt(orderNum));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.orderNum.asc());

        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public void updateOrderNum(Long id, Integer orderNum) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.id.eq(id));

        UpdateChain.of(GoodsType.class)
                .set(table.orderNum, orderNum)
                .where(condition)
                .update();
    }

    @Override
    public int getMaxShowOrder(Long goodsId, Integer comboType) {
        QueryWrapper wrapper = QueryWrapper.create()
                .select(QueryMethods.max(table.orderNum))
                .from(table)
                .where(table.goodsId.eq(goodsId).and(table.comboType.eq(comboType)));

        Integer integer = getMapper().selectObjectByQueryAs(wrapper, Integer.class);
        return NepUtil.nullToZero(integer);
    }

    @Override
    public List<GoodsType> listByGoodsIdIn(List<Long> goodsIds) {
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.goodsId.in(goodsIds))
                .orderBy(table.goodsId.asc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public boolean updateDiscountStatus(Long id, Integer discountStatus, String staffUid, String staffName) {
        return UpdateChain.of(GoodsType.class)
                .set(table.discountStatus, discountStatus)
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .where(table.id.eq(id))
                .update();
    }

}
